home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 October: Technology Seed / ADC Seed CD - October 1999.toast / FireWire / FireWire_2.1_SDK_DR3 / Source / FWiX / FWiXApp / FWiXprefs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-05-17  |  29.6 KB  |  1,139 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        FWiXprefs.c
  3.  
  4.     Contains:    Preferences dialog and initialization.
  5.  
  6.     Version:    1.0
  7.  
  8.     Written by:    Jay Lloyd
  9.     
  10.     Copyright:    © 1996-1999 by Apple Computer, Inc., all rights reserved.
  11.  
  12.     File Ownership:
  13.  
  14.         DRI:                Jay Lloyd
  15.  
  16.         Other Contact:        
  17.  
  18.         Technology:            FireWire
  19.  
  20.     Writers:
  21.  
  22.         (DCB)    Clinton Bauder
  23.         (jkl)    Jay Lloyd
  24.  
  25.     Change History (most recent first):
  26.  
  27.       <FW11>      4/8/99    jkl        More interface cleanup.
  28.       <FW10>      2/2/99    DCB        Fix for new MI headers.
  29.        <FW9>    12/19/98    DCB        More cleanup for SDK.
  30.          <8>     1/15/98    jkl        Update for new headers.
  31.        <FW7>     6/19/97    jkl        Added a preference for saving the icon view.
  32.        <FW6>     6/10/97    jkl        Updated qd global name.
  33.        <FW5>     5/27/97    jkl        Corrected a problem with the receive folder being created that
  34.                                     would cause a receive folder location other than the default to
  35.                                     not get saved.
  36.        <FW4>      5/7/97    jkl        Updated data structure names.
  37.        <FW3>     4/29/97    jkl        Fixed my bbs initials to not conflict with Jim Luther.
  38.        <FW2>     4/29/97    jkl        Added a call to Handle update event to the preferences dialog
  39.                                     event filter routine.
  40.        <FW1>     3/18/97    jkl        first checked in
  41. */
  42.  
  43. #include <Files.h>
  44. #include <Dialogs.h>
  45. #include <Sound.h>
  46. #include <Resources.h>
  47. #include <StandardFile.h>
  48. #include <Script.h>
  49. #include <Aliases.h>
  50. #include <Folders.h>
  51. #include <TextUtils.h>
  52. #include <QuickDraw.h>
  53. #include <TextEdit.h>
  54. #include <Fonts.h>
  55. #if !ETO_Build
  56. #include <ControlDefinitions.h>
  57. #endif
  58.  
  59. #include "FWiX.h"
  60. #include "FWiXmain.h"
  61. #include "FWiXdrag.h"
  62. #include "FWiXprefs.h"
  63.  
  64. static FSSpec        gDeskFolderSpec;
  65. static Str255        gSelectString = "\pSelect";
  66. static Str31        gDesktopFName = "\pDesktop";
  67. static FSSpec        gSelectSpec;
  68.  
  69. extern FWXAppDataPtr        gpFWXAppData;
  70.  
  71. ////////////////////////////////////////////////////////////////////////////////
  72. //
  73. //    HandlePrefsDialog
  74. //
  75. //    Handle the Preferences dialog.
  76. //
  77. OSErr HandlePrefsDialog (void)
  78. {
  79.     DialogPtr            pDlog;
  80.     UserItemUPP            pUserDefProc;
  81.     ModalFilterUPP        pModalFilterProc;
  82.     Ptr                    pTemp;
  83.     Handle                item;
  84.     Rect                box;
  85.     SInt16                itemHit;
  86.     OSErr                err = noErr;
  87.     
  88.     pUserDefProc = NewUserItemProc(DrawDefaultButton);
  89.     if (pUserDefProc == nil)
  90.         return memFullErr;
  91.         
  92.     pModalFilterProc = NewModalFilterProc(HandlePrefsEventFilter);
  93.     if (pModalFilterProc == nil)
  94.         return memFullErr;
  95.     
  96.     // set received items folder name
  97.     ParamText(gpFWXAppData->fwixReceiveFolder.name, "\p", "\p", "\p");
  98.     
  99.     pDlog = GetNewDialog(kPrefsDlogID, nil, (WindowPtr) -1);
  100.     if (pDlog != nil) {
  101.         // get handle to default button user item and replace with draw proc
  102.         GetDialogItem(pDlog, kDefaultUserItem, &itemHit, &item, &box);
  103.         SetDialogItem(pDlog, kDefaultUserItem, itemHit,
  104.                         (Handle) pUserDefProc, &box);
  105.         SetupDialogPrefs(pDlog);
  106.         HiliteMenu(0);      // unhilight menu title
  107.         
  108.         // JKL *** select sound name
  109.         ShowWindow(pDlog);
  110.     } else
  111.         err = ResError();
  112.     
  113.     if (err == noErr)
  114.     {
  115.         do
  116.         {
  117.             ModalDialog(pModalFilterProc, &itemHit);
  118.             HandlePrefsDialogEvent(pDlog, itemHit);            
  119.         } while ((itemHit != kOKButton) && (itemHit != kCancelButton));
  120.         
  121.         HideWindow(pDlog);    
  122.         if (itemHit == kOKButton)
  123.             err = UpdateDialogPrefs(pDlog);
  124.     
  125.         // clean up dialog memory allocations
  126.         pTemp = (Ptr) GetWRefCon(pDlog);
  127.         DisposePtr(pTemp);
  128.         DisposeRoutineDescriptor(pModalFilterProc);
  129.         DisposeRoutineDescriptor(pUserDefProc);
  130.         DisposeDialog(pDlog);
  131.     }
  132.     return err;
  133. }
  134.  
  135. //////////////////////////////////////////////////////////////////////////////
  136. //
  137. //    HandlePrefsDialogEvent
  138. //
  139. //    Handle mouseDowns in dialog items
  140. //
  141. static void    HandlePrefsDialogEvent(
  142.     DialogPtr                pDlog,
  143.     SInt16                    itemHit)
  144. {
  145.     Str255                    s;
  146.     PopupPrivateDataHandle    hPopup;
  147.     RgnHandle                hRgn;
  148.     WindowPtr                curPort;
  149.     Handle                    itemHandle;
  150.     FSSpecPtr                pDropFolder;
  151.     Rect                    box;
  152.     StandardFileReply        reply;
  153.     SInt16                    itemType;
  154.     SInt16                    curVal;
  155.     SInt16                    whichSound;
  156.     SInt16                    curAttributes;
  157.  
  158.     if ((itemHit >= kFlashBox) && (itemHit <= kOpenBox))
  159.     {
  160.         GetDialogItem(pDlog, itemHit, &itemType, &itemHandle, &box);
  161.         curVal = GetControlValue((ControlHandle) itemHandle);
  162.         SetControlValue((ControlHandle) itemHandle, 1 - curVal);
  163.  
  164.         if (itemHit == kSoundBox)
  165.         {
  166.             GetDialogItem(pDlog, kSoundPopup, &itemType, &itemHandle, &box);
  167.             hPopup = (PopupPrivateDataHandle) (**((ControlHandle) itemHandle)).contrlData;
  168.     
  169.             if (curVal == 0)
  170.                 EnableItem((**hPopup).mHandle, 0);
  171.             else
  172.                 DisableItem((**hPopup).mHandle, 0);
  173.             
  174.             hRgn = NewRgn();
  175.             if (hRgn != nil)
  176.             {
  177.                 RectRgn(hRgn, &(**((ControlHandle) itemHandle)).contrlRect);
  178.                 UpdateControls(pDlog, hRgn);
  179.                 DisposeRgn(hRgn);
  180.             }
  181.             else
  182.                 DrawControls(pDlog);
  183.         }
  184.     }
  185.     else if ((itemHit >= kCancelRadio) && (itemHit <= kOverwriteRadio))
  186.     {
  187.         GetDialogItem(pDlog, kCancelRadio, &itemType, &itemHandle, &box);
  188.         if (itemHit == kCancelRadio)
  189.             SetControlValue((ControlHandle) itemHandle, 1);
  190.         else
  191.             SetControlValue((ControlHandle) itemHandle, 0);
  192.     
  193.         GetDialogItem(pDlog, kRenameRadio, &itemType, &itemHandle, &box);
  194.         if (itemHit == kRenameRadio)
  195.             SetControlValue((ControlHandle) itemHandle, 1);
  196.         else
  197.             SetControlValue((ControlHandle) itemHandle, 0);
  198.     
  199.         GetDialogItem(pDlog, kOverwriteRadio, &itemType, &itemHandle, &box);
  200.         if (itemHit == kOverwriteRadio)
  201.             SetControlValue((ControlHandle) itemHandle, 1);
  202.         else
  203.             SetControlValue((ControlHandle) itemHandle, 0);
  204.     }
  205.     else if (itemHit == kSoundPopup)
  206.     {
  207.         // if the play sound box is checked, play the sound
  208.         GetDialogItem(pDlog, kSoundBox, &itemType, &itemHandle, &box);
  209.         curVal = GetControlValue((ControlHandle) itemHandle);
  210.         if (curVal == 1)
  211.         {
  212.             GetDialogItem(pDlog, kSoundPopup, &itemType, &itemHandle, &box);
  213.             whichSound = GetControlValue((ControlHandle) itemHandle);
  214.             hPopup = (PopupPrivateDataHandle) (**((ControlHandle) itemHandle)).contrlData;    
  215.             GetMenuItemText((**hPopup).mHandle, whichSound, s);
  216.             itemHandle = GetNamedResource('snd ', s);
  217.             if (itemHandle != nil)
  218.             {
  219.                 curAttributes = GetResAttrs(itemHandle);
  220.                 if (curAttributes & resPurgeable)
  221.                     HNoPurge(itemHandle);
  222.                 SndPlay(nil, (SndListHandle) itemHandle, false);
  223.                 SetResAttrs(itemHandle, curAttributes);
  224.                 ReleaseResource(itemHandle);
  225.             }
  226.         }
  227.     }
  228.     else if (itemHit == kDropButton)
  229.     {
  230.         GetDropFolder(&reply);
  231.         if (reply.sfGood) {
  232.             pDropFolder = (FSSpecPtr) GetWRefCon(pDlog);
  233.             FSMakeFSSpec(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, pDropFolder);
  234.             ParamText(pDropFolder->name, "\p", "\p", "\p");
  235.  
  236.             GetPort(&curPort);
  237.             SetPort(pDlog);
  238.             InvalRect(&(pDlog->portRect));
  239.             SetPort(curPort);
  240.         }
  241.     }
  242. }
  243.  
  244. //////////////////////////////////////////////////////////////////////////////
  245. //
  246. //    GetDeskFolderSpec
  247. //
  248. //    Create FSSpec for Desktop folder
  249. //
  250. static OSErr GetDeskFolderSpec(
  251.     FSSpec             *pFileSpec)
  252. {
  253.     OSErr            err;
  254.     
  255.     pFileSpec->name[0] = '\0';
  256.     err = FindFolder(kOnSystemDisk, kDesktopFolderType, kDontCreateFolder,
  257.                         &pFileSpec->vRefNum, &pFileSpec->parID);
  258.     if (err)
  259.         return err;
  260.         
  261.     err = FSMakeFSSpec(pFileSpec->vRefNum, pFileSpec->parID, pFileSpec->name,
  262.                         pFileSpec);
  263.     return err;
  264. }
  265.  
  266. //////////////////////////////////////////////////////////////////////////////
  267. //
  268. //    GetDropFolder
  269. //
  270. //    Select a fwix receive folder
  271. //
  272. static OSErr GetDropFolder (
  273.     StandardFileReply        *reply )
  274. {
  275.     FileFilterYDUPP            pMyFileFilter;
  276.     DlgHookYDUPP            pMyDlogHook;
  277.     Point                    where = {-1,-1};
  278.     OSErr                    err = noErr;
  279.     
  280.     pMyFileFilter = NewFileFilterYDProc(FilterAllFiles);
  281.     if (pMyFileFilter == nil)
  282.         return memFullErr;
  283.     pMyDlogHook = NewDlgHookYDProc(DialogHook);
  284.     if (pMyDlogHook == nil)
  285.         return memFullErr;
  286.     GetDeskFolderSpec(&gDeskFolderSpec);
  287.         
  288.     CustomGetFile(pMyFileFilter, -1, nil, reply, kCustomGetFileResID,
  289.                     where, pMyDlogHook, nil, nil, nil, reply);
  290.     
  291.     DisposeRoutineDescriptor(pMyDlogHook);
  292.     DisposeRoutineDescriptor(pMyFileFilter);
  293.     return err;
  294. }
  295.  
  296. //////////////////////////////////////////////////////////////////////////////
  297. //
  298. //    DialogHook
  299. //
  300. //    Handle custom get file dialog actions.
  301. //
  302. static pascal SInt16 DialogHook (
  303.     SInt16                    item,
  304.     DialogPtr                pDlog,
  305.     Ptr                        pMyData)
  306. {
  307.     UserItemUPP                pUserDefProc;
  308.     StandardFileReply        *reply;
  309.     FSSpec                    curSpec;
  310.     OSType                    refCon;
  311.     Handle                    hDlogItem;
  312.     Rect                    box;
  313.     SInt16                    itemHit;
  314.     static FSSpec            lastSpec;
  315.  
  316.     refCon = GetWRefCon(pDlog);
  317.     if (refCon != sfMainDialogRefCon)
  318.         return item;
  319.     
  320.     reply = (StandardFileReply *) pMyData;
  321.     
  322.     switch (item)
  323.     {
  324.         case sfHookFirstCall:
  325.             lastSpec.vRefNum = -9999;                // init to ridiculous valuesx
  326.             pUserDefProc = NewUserItemProc(DrawUserSelection);
  327.             GetDialogItem(pDlog, kCustomGetUserItem, &itemHit, &hDlogItem, &box);
  328.             SetDialogItem(pDlog, kCustomGetUserItem, itemHit, (Handle) pUserDefProc, &box);
  329.             reply->sfFile = gpFWXAppData->fwixReceiveFolder;
  330.             item = sfHookChangeSelection;
  331.             break;
  332.         
  333.         case sfHookLastCall:
  334.             GetDialogItem(pDlog, kCustomGetUserItem, &itemHit, &hDlogItem, &box);
  335.             DisposeRoutineDescriptor((UniversalProcPtr) itemHit);
  336.             break;
  337.         
  338.         case sfHookNullEvent:
  339.             if (!SameFile(&reply->sfFile, &lastSpec))
  340.             {
  341.                 curSpec = reply->sfFile;
  342.                 FSMakeFSSpec(curSpec.vRefNum, curSpec.parID, curSpec.name, &curSpec);
  343.                 GetDialogItem(pDlog, kCustomGetUserItem, &itemHit, &hDlogItem, &box);
  344.                 InvalRect(&box);
  345.                 //SetSelectButtonName(&curSpec, pDlog);
  346.                 lastSpec = reply->sfFile;
  347.                 gSelectSpec = curSpec;
  348.             }
  349.             break;
  350.  
  351.         case kSelectItem:
  352.             item = sfItemOpenButton;
  353.             break;
  354.     }    
  355.     return item;
  356. }
  357.  
  358. //////////////////////////////////////////////////////////////////////////////
  359. //
  360. //    SameFile
  361. //
  362. //    Checks two file specs to see if they are equal
  363. //
  364. static Boolean SameFile (
  365.     FSSpec                *spec1,
  366.     FSSpec                *spec2)
  367. {
  368.     if (spec1->vRefNum != spec2->vRefNum)
  369.         return false;
  370.     if (spec1->parID != spec2->parID)
  371.         return false;
  372.     if (!EqualString( spec1->name, spec2->name, false, true))
  373.         return false;
  374.     return true;
  375. }
  376.  
  377. //////////////////////////////////////////////////////////////////////////////
  378. //
  379. //    SetSelectButtonName
  380. //
  381. //    This routine gets the "Select" button from the CustomGetFile dialog and
  382. //    the filename string from the FSSpec parameter.  It set the buttons name
  383. //    to Select “filename”, truncating the filemane if needed.  The button is
  384. //    dimmed if kCanSelectDesktop is false and the FSSpec is desktop folder.
  385. static void SetSelectButtonName (
  386.     FSSpec            *spec,
  387.     DialogPtr        theDlg)
  388. {
  389.     HParamBlockRec    pb;
  390.     Handle            iHndl;
  391.     Rect            iRect;
  392.     Str63            selNameTrunc = "\p";
  393.     Str255            btnName = "\p";
  394.     SInt16            iType;
  395.     SInt16            btnWidth;
  396.     OSErr            err;
  397.     Boolean            hilited = true;
  398.     
  399.     pb.volumeParam.ioVRefNum = spec->vRefNum;
  400.     pb.volumeParam.ioNamePtr = nil;
  401.     pb.volumeParam.ioVolIndex = 0;        // use ioVRefNum only
  402.     err = PBHGetVInfoSync(&pb);
  403.     if (err == noErr) {
  404.         if ((pb.volumeParam.ioVAtrb & 0x0080) != 0) {
  405.             // volume locked by hardware
  406.             hilited = false;
  407.         } else if ((pb.volumeParam.ioVAtrb & 0x8000) != 0) {
  408.             // volume locked by software
  409.             hilited = false;
  410.         }
  411.     }
  412.  
  413.     if (SameFile(spec, &gDeskFolderSpec)) {
  414.         AppendStrToStr(selNameTrunc, gDesktopFName, 63);
  415.         hilited = kCanSelectDesktop;
  416.     } else
  417.         AppendStrToStr( selNameTrunc, spec->name, 63 ) ;
  418.     
  419.     
  420.     GetDItem(theDlg,kSelectItem,&iType,&iHndl,&iRect);
  421.     
  422.     // truncate select name to fit in button
  423.     btnWidth = iRect.right - iRect.left;
  424.     btnWidth -= StringWidth(gSelectString);
  425.     btnWidth -= StringWidth("\p “”  ");
  426.     TruncString(btnWidth, selNameTrunc, smTruncMiddle);
  427.     
  428.     // build button name string
  429.     AppendStrToStr( btnName, gSelectString, 255 ) ;
  430.     AppendStrToStr( btnName, "\p “", 255) ;
  431.     AppendStrToStr( btnName, selNameTrunc, 255) ;
  432.     AppendStrToStr( btnName, "\p”", 255) ;
  433.     
  434.     SetCTitle((ControlRef)iHndl, btnName);
  435.  
  436.     if (hilited)
  437.         HiliteControl((ControlRef)iHndl,0);
  438.     else
  439.         HiliteControl((ControlRef)iHndl,255);        
  440. }
  441.  
  442. //////////////////////////////////////////////////////////////////////////////
  443. //
  444. //    AppendStrToStr
  445. //
  446. //    Concat two strings.
  447. //
  448. static void AppendStrToStr (
  449.     StringPtr                dst,
  450.     StringPtr                src,
  451.     UInt8                    maxDstLen)
  452. {
  453.     short        offset = dst[0]+1;
  454.     short        size   = src[0];
  455.     
  456.     if ( dst[0] + src[0] > maxDstLen)            // make sure were not too big
  457.         size = maxDstLen - dst[0];                // you should return a warning here
  458.     BlockMove(src+1, dst+offset, size);
  459.     dst[0] += size;
  460. }
  461.  
  462. //////////////////////////////////////////////////////////////////////////////
  463. //
  464. //    MyFilterAllFiles
  465. //
  466. //    Removes all files from dialog box, only get directories and volumes.
  467. //
  468. static pascal Boolean FilterAllFiles (
  469.     CInfoPBPtr                pb,
  470.     Ptr                        pMyData)
  471. {
  472.     if (pb->hFileInfo.ioFlAttrib & ioDirMask)
  473.         return false;
  474.     return true;
  475. }
  476.  
  477. //////////////////////////////////////////////////////////////////////////////
  478. //
  479. //    UpdateDialogPrefs
  480. //
  481. //    After pressing OK, update settings
  482. //
  483. static OSErr UpdateDialogPrefs (
  484.     DialogPtr                pDlog)
  485. {
  486.     Handle                    itemHandle;
  487.     PopupPrivateDataHandle    hPopup;
  488.     FSSpecPtr                pNewDropFolder;
  489.     WindowDataPtr            pWinData;
  490.     RecvNodePtr                pRecvNode;
  491.     CurFileInfoPtr            pTxInfo;
  492.     Str255                    s;
  493.     Rect                    box;
  494.     UInt32                    notifyAndConflictPrefs;
  495.     SInt16                    itemType;
  496.     SInt16                    whichSound;
  497.     OSErr                    err;
  498.     
  499.     notifyAndConflictPrefs = 0;
  500.     
  501.     // Get checkbox values
  502.     GetDialogItem(pDlog, kFlashBox, &itemType, &itemHandle, &box);
  503.     if (GetControlValue((ControlHandle) itemHandle))
  504.         notifyAndConflictPrefs |= kNotifyFlash;
  505.         
  506.     GetDialogItem(pDlog, kAlertBox, &itemType, &itemHandle, &box);
  507.     if (GetControlValue((ControlHandle) itemHandle))
  508.         notifyAndConflictPrefs |= kNotifyAlert;
  509.         
  510.     GetDialogItem(pDlog, kSoundBox, &itemType, &itemHandle, &box);
  511.     if (GetControlValue((ControlHandle) itemHandle))
  512.         notifyAndConflictPrefs |= kNotifySound;
  513.         
  514.     GetDialogItem(pDlog, kOpenBox, &itemType, &itemHandle, &box);
  515.     if (GetControlValue((ControlHandle) itemHandle))
  516.         notifyAndConflictPrefs |= kNotifyOpen;
  517.     
  518.     // Get radio box values    
  519.     GetDialogItem(pDlog, kCancelRadio, &itemType, &itemHandle, &box);
  520.     if (GetControlValue((ControlHandle) itemHandle))
  521.         notifyAndConflictPrefs |= kConflictCancel;
  522.         
  523.     GetDialogItem(pDlog, kRenameRadio, &itemType, &itemHandle, &box);
  524.     if (GetControlValue((ControlHandle) itemHandle))
  525.         notifyAndConflictPrefs |= kConflictRename;
  526.         
  527.     GetDialogItem(pDlog, kOverwriteRadio, &itemType, &itemHandle, &box);
  528.     if (GetControlValue((ControlHandle) itemHandle))
  529.         notifyAndConflictPrefs |= kConflictOverwrite;
  530.         
  531.     // Update globals and resource
  532.     gpFWXAppData->fwixPrefs &= kIconView;
  533.     gpFWXAppData->fwixPrefs |= notifyAndConflictPrefs;
  534.         
  535.     // get notify sound name
  536.     GetDialogItem(pDlog, kSoundPopup, &itemType, &itemHandle, &box);
  537.     whichSound = GetControlValue((ControlHandle) itemHandle);
  538.     hPopup = (PopupPrivateDataHandle) (**((ControlHandle) itemHandle)).contrlData;    
  539.     GetMenuItemText((**hPopup).mHandle, whichSound, s);
  540.     BlockMove(s, gpFWXAppData->fwixNotifySound, s[0] + 1);
  541.         
  542.     // get drop folder and update open drop menu item and receive node records dirID
  543.     pNewDropFolder = (FSSpecPtr) GetWRefCon(pDlog);
  544.     gpFWXAppData->fwixReceiveFolder = *pNewDropFolder;
  545.     
  546.     // update menu item
  547.     GetMenuItemText(GetMenuHandle(kFileMenuID), kOpenDropMenuItem, s);
  548.     BlockMove(    gpFWXAppData->fwixReceiveFolder.name + 1,
  549.                 s + 7,
  550.                 gpFWXAppData->fwixReceiveFolder.name[0]);
  551.     s[0] = 6 + gpFWXAppData->fwixReceiveFolder.name[0] + 1;
  552.     s[s[0]] = '”';
  553.     SetMenuItemText(GetMenuHandle(kFileMenuID), kOpenDropMenuItem, s);
  554.     
  555.     // Update the drop folder in receive info records
  556.     // Traverse the node list updating each node records dir id
  557.     pWinData = (WindowDataPtr) GetWRefCon(gpFWXAppData->pSenderWindow);
  558.     
  559.     pRecvNode = pWinData->pRecvNodeList;
  560.     while (pRecvNode != nil) {
  561.         GetCurFileInfo(pRecvNode->nodeID, &pTxInfo, false);
  562.         InitRecvFolder(& (pTxInfo->curDirID));
  563.         pRecvNode = (RecvNodePtr) pRecvNode->pNextNode;
  564.     }
  565.  
  566.     // update notification record
  567.     UpdateNotification(gpFWXAppData->pNotifyRec);
  568.     
  569.     err = UpdatePrefsFile();
  570.     return err;
  571. }
  572.     
  573. OSErr UpdatePrefsFile (void)
  574. {
  575.     Handle                    h;
  576.     AliasHandle                hAlias;
  577.     SInt32                    dirID;
  578.     FSSpec                    prefsSpec;
  579.     SInt16                    vRefNum;
  580.     SInt16                    fileRefNum;
  581.     OSErr                    err;
  582.         
  583.     // write the changes to the prefs file
  584.     err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, &vRefNum, &dirID);
  585.     if (err != noErr)
  586.         return err;
  587.         
  588.     // create the preferences file if it does not exist
  589.     h = Get1Resource('STR ', kPrefsFileResourceID);
  590.     if (h == nil)
  591.         return ResError();
  592.     DetachResource(h);
  593.     HLock(h);    
  594.     err = FSMakeFSSpec(vRefNum, dirID, (ConstStr255Param) *h, &prefsSpec);
  595.     HUnlock(h);
  596.     DisposeHandle(h);
  597.     if (err == fnfErr)
  598.     {
  599.         FSpCreateResFile(&prefsSpec, 'fwfx', 'pref', smSystemScript);
  600.         err = ResError();
  601.         if (err != noErr)
  602.             return err;
  603.     }
  604.  
  605.     fileRefNum = FSpOpenResFile(&prefsSpec, fsRdWrPerm);
  606.     err = ResError();
  607.     if (err == noErr)
  608.     {
  609.         h = Get1Resource(kPrefsResourceType, kPrefsResourceID);
  610.         if (h != nil)
  611.         {
  612.             **((UInt32 **) h) = gpFWXAppData->fwixPrefs;
  613.             ChangedResource(h);
  614.             ReleaseResource(h);
  615.         }
  616.             
  617.         h = Get1Resource('STR ', kSndPrefsResourceID);
  618.         if (h != nil)
  619.         {
  620.             SetHandleSize(h, gpFWXAppData->fwixNotifySound[0] + 1);
  621.             err = MemError();
  622.             BlockMove(gpFWXAppData->fwixNotifySound, *h, gpFWXAppData->fwixNotifySound[0] + 1);
  623.             ChangedResource(h);
  624.             ReleaseResource(h);
  625.         }
  626.         
  627.         h = Get1Resource(rAliasType, kDropPrefsResourceID);
  628.         if (h != nil)
  629.         {
  630.             err = NewAliasMinimal(&gpFWXAppData->fwixReceiveFolder, (AliasHandle *) &hAlias);
  631.             SetHandleSize(h, (**hAlias).aliasSize);
  632.             BlockMove(*hAlias, *h, (**hAlias).aliasSize);
  633.             ChangedResource(h);
  634.             ReleaseResource(h);
  635.         }
  636.         CloseResFile(fileRefNum);
  637.         FlushVol(nil, vRefNum);
  638.     }
  639.     
  640.     return err;
  641. }
  642.  
  643. //////////////////////////////////////////////////////////////////////////////
  644. //
  645. //    SetupDialogPrefs
  646. //
  647. //    Initialize dialog item settings before opening
  648. //
  649. static OSErr SetupDialogPrefs (
  650.     DialogPtr                pDlog)
  651. {
  652.     Handle                    itemHandle;
  653.     FSSpecPtr                pTempReceiveFolder;
  654.     PopupPrivateDataHandle    hPopup;
  655.     Str255                    soundText;
  656.     Rect                    box;
  657.     SInt16                    itemType;
  658.     SInt16                    itemVal;
  659.     SInt16                    activeRadio;
  660.     SInt16                    numSounds;
  661.     SInt16                    soundItem;
  662.     
  663.     // setup check boxes
  664.     GetDialogItem(pDlog, kFlashBox, &itemType, &itemHandle, &box);
  665.     SetControlValue((ControlHandle) itemHandle,
  666.         (gpFWXAppData->fwixPrefs & kNotifyFlash) ? 1 : 0);
  667.         
  668.     GetDialogItem(pDlog, kAlertBox, &itemType, &itemHandle, &box);
  669.     SetControlValue((ControlHandle) itemHandle,
  670.         (gpFWXAppData->fwixPrefs & kNotifyAlert) ? 1 : 0);
  671.         
  672.     GetDialogItem(pDlog, kSoundBox, &itemType, &itemHandle, &box);
  673.     SetControlValue((ControlHandle) itemHandle,
  674.         (gpFWXAppData->fwixPrefs & kNotifySound) ? 1 : 0);
  675.         
  676.     GetDialogItem(pDlog, kOpenBox, &itemType, &itemHandle, &box);
  677.     SetControlValue((ControlHandle) itemHandle,
  678.         (gpFWXAppData->fwixPrefs & kNotifyOpen) ? 1 : 0);
  679.  
  680.     // setup radio buttons, zero them all then set the preference
  681.     GetDialogItem(pDlog, kCancelRadio, &itemType, &itemHandle, &box);
  682.     SetControlValue((ControlHandle) itemHandle, 0);
  683.         
  684.     GetDialogItem(pDlog, kRenameRadio, &itemType, &itemHandle, &box);
  685.     SetControlValue((ControlHandle) itemHandle, 0);
  686.         
  687.     GetDialogItem(pDlog, kOverwriteRadio, &itemType, &itemHandle, &box);
  688.     SetControlValue((ControlHandle) itemHandle, 0);
  689.         
  690.     activeRadio = (gpFWXAppData->fwixPrefs & 0x0F) >> 1;
  691.     GetDialogItem(pDlog, kCancelRadio + activeRadio, &itemType, &itemHandle, &box);
  692.     SetControlValue((ControlHandle) itemHandle, 1);
  693.     
  694.     // setup the sound popup
  695.     GetDialogItem(pDlog, kSoundPopup, &itemType, &itemHandle, &box);
  696.     hPopup = (PopupPrivateDataHandle) (**((ControlHandle) itemHandle)).contrlData;
  697.     
  698.     numSounds = CountMItems((**hPopup).mHandle);
  699.     for (soundItem = 1; soundItem < numSounds; soundItem++)
  700.     {
  701.         GetMenuItemText((**hPopup).mHandle, soundItem, soundText);
  702.         if (EqualString(gpFWXAppData->fwixNotifySound, soundText, true, true))
  703.             break;
  704.     }
  705.     SetControlValue((ControlHandle) itemHandle, soundItem);
  706.     
  707.     GetDialogItem(pDlog, kSoundBox, &itemType, &itemHandle, &box);
  708.     itemVal = GetControlValue((ControlHandle) itemHandle);
  709.     if (itemVal == 1)
  710.         EnableItem((**hPopup).mHandle, 0);
  711.     else
  712.         DisableItem((**hPopup).mHandle, 0);
  713.  
  714.     // setup receive folder fsspec, stored in refCon until done
  715.     pTempReceiveFolder = (FSSpecPtr) NewPtr(sizeof(FSSpec));
  716.     if (pTempReceiveFolder == nil)
  717.         return memFullErr;
  718.         
  719.     *pTempReceiveFolder = gpFWXAppData->fwixReceiveFolder;
  720.     SetWRefCon(pDlog, (SInt32) pTempReceiveFolder);
  721.     
  722.     return noErr;
  723. }
  724.  
  725. //////////////////////////////////////////////////////////////////////////////
  726. //
  727. //    HandlePrefsEventFilter
  728. //
  729. //    Handles modal dialog filter
  730. //
  731. static pascal Boolean HandlePrefsEventFilter(
  732.     DialogPtr        pDlog,
  733.     EventRecord        *pEvent,
  734.     SInt16            *itemHit)
  735. {
  736.     Handle            item;
  737.     Rect            box;
  738.     UInt32            finalTicks;
  739.     SInt16            itemType;
  740.     UInt8            key;
  741.     Boolean            handledIt;
  742.     
  743.     handledIt = false;
  744.     
  745.     switch (pEvent->what)
  746.     {
  747.         case keyDown:
  748.             key = pEvent->message & charCodeMask;
  749.             
  750.             if (key == kReturnKey || key == kEnterKey)
  751.             {
  752.                 GetDialogItem(pDlog, kOKButton, &itemType, &item, &box);
  753.                 HiliteControl((ControlHandle) item, kControlButtonPart);
  754.                 Delay(8, &finalTicks);
  755.                 HiliteControl((ControlHandle) item, 0);
  756.                 handledIt = true;
  757.                 *itemHit = kOKButton;
  758.             }
  759.             else if (((pEvent->modifiers & cmdKey) && (key == kPeriodKey)) || (key == kEscapeKey))
  760.             {
  761.                 GetDialogItem(pDlog, kCancelButton, &itemType, &item, &box);
  762.                 HiliteControl((ControlHandle) item, kControlButtonPart);
  763.                 Delay(8, &finalTicks);
  764.                 HiliteControl((ControlHandle) item, 0);
  765.                 handledIt = true;
  766.                 *itemHit = kCancelButton;
  767.             }
  768.             break;
  769.         
  770.         case nullEvent:
  771.             HandleIdle();
  772.             break;
  773.         
  774.         case updateEvt:
  775.             HandleUpdateEvent(pEvent);
  776.             break;
  777.         
  778.         case activateEvt:
  779.             break;
  780.     }
  781.     return handledIt;
  782. }
  783.  
  784. //////////////////////////////////////////////////////////////////////////////
  785. //
  786. //    DrawUserSelection
  787. //
  788. //    Draws the selected folder text.
  789. //
  790. static pascal void DrawUserSelection(
  791.     WindowPtr        theWindow,
  792.     SInt16            itemNo)
  793. {
  794.     WindowPtr        curPort;
  795.     Handle            item;
  796.     Rect            box;
  797.     SInt32            sLength = 47;
  798.     Str255            s = "Click the Select button to select the folder: “";
  799.     SInt16            itemType;
  800.     SInt16            oldFont, oldSize;
  801.     
  802.     GetDialogItem(theWindow, itemNo, &itemType, &item, &box);
  803.     GetPort(&curPort);
  804.     SetPort(theWindow);
  805.     oldFont = theWindow->txFont;
  806.     oldSize = theWindow->txSize;
  807.     TextFont(kFontIDGeneva);
  808.     TextSize(9);
  809.     BlockMove(gSelectSpec.name + 1, s + 47, gSelectSpec.name[0]);
  810.     sLength += gSelectSpec.name[0];
  811.     s[sLength] = '”';
  812.     sLength++;
  813.     TETextBox(s, sLength, &box, teJustLeft);
  814.     TextFont(oldFont);
  815.     TextSize(oldSize);
  816.     SetPort(curPort);
  817. }
  818.  
  819. //////////////////////////////////////////////////////////////////////////////
  820. //
  821. //    DrawDefaultButton
  822. //
  823. //    Draws outline around default button
  824. //
  825. static pascal void DrawDefaultButton(
  826.     WindowPtr        theWindow,
  827.     SInt16            itemNo)
  828. {
  829.     WindowPtr        curPort;
  830.     Handle            item;
  831.     PenState        curPen;
  832.     Rect            box;
  833.     SInt16            itemType;
  834.     SInt16            buttonOval;
  835.     
  836.     GetDialogItem(theWindow, itemNo, &itemType, &item, &box);
  837.     GetPort(&curPort);
  838.     SetPort(theWindow);
  839.     GetPenState(&curPen);
  840.     PenNormal();
  841.  
  842.     PenPat(& qd.black);
  843.     PenSize(3, 3);
  844.     buttonOval = ((box.bottom - box.top) / 2) + 2;
  845.     FrameRoundRect(&box, buttonOval, buttonOval);
  846.  
  847.     SetPenState(& curPen);
  848.     SetPort(curPort);
  849. }
  850.  
  851. ////////////////////////////////////////////////////////////////////////////////
  852. //
  853. //    SaveWindowPos
  854. //
  855. //    Save the window position in prefs.
  856. //
  857. OSErr SaveWindowPos (
  858.     WindowPtr            pWin)
  859. {
  860.     Handle                h;
  861.     Rect                winRect;
  862.     FSSpec                prefsSpec;
  863.     SInt32                dirID;
  864.     SInt16                fileRef, volumeRef;
  865.     OSErr                err;
  866.  
  867.     winRect = (**(((WindowPeek) pWin)->contRgn)).rgnBBox;
  868.  
  869.     // find the preferences folder
  870.     err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, &volumeRef, &dirID);
  871.     if (err != noErr)
  872.         return err;
  873.     
  874.     // open the preferences file
  875.     h = Get1Resource('STR ', kPrefsFileResourceID);
  876.     if (h == nil)
  877.         return ResError();
  878.     DetachResource(h);
  879.     HLock(h);    
  880.     err = FSMakeFSSpec(volumeRef, dirID, (ConstStr255Param) *h, &prefsSpec);
  881.     HUnlock(h);
  882.     DisposeHandle(h);
  883.     if (err == noErr)
  884.     {
  885.         fileRef = FSpOpenResFile(&prefsSpec, fsRdWrPerm);
  886.         err = ResError();
  887.         
  888.         if (err == noErr)
  889.         {
  890.             // setup the preferences flags
  891.             h = Get1Resource('win ', kWinPosPrefsID);
  892.             if (h == nil)
  893.             {
  894.                 h = NewHandle(sizeof(Rect));
  895.                 **((Rect **) h) = winRect;
  896.                 AddResource(h, kWinPosPrefsType, kWinPosPrefsID, nil);
  897.                 UpdateResFile(fileRef);
  898.                 ReleaseResource(h);
  899.             }
  900.             else
  901.             {
  902.                 **((Rect **) h) = winRect;
  903.                 ChangedResource(h);
  904.                 ReleaseResource(h);
  905.             }
  906.             CloseResFile(fileRef);
  907.         }
  908.     }
  909.     return err;
  910. }
  911.  
  912. ////////////////////////////////////////////////////////////////////////////////
  913. //
  914. //    GetWindowPos
  915. //
  916. //    Retrieves the window position in prefs.
  917. //
  918. OSErr GetWindowPos (
  919.     Rect                *r)
  920. {
  921.     Handle                h;
  922.     FSSpec                prefsSpec;
  923.     SInt32                dirID;
  924.     SInt16                fileRef, volumeRef;
  925.     OSErr                err;
  926.  
  927.     // find the preferences folder
  928.     err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, &volumeRef, &dirID);
  929.     if (err != noErr)
  930.         return err;
  931.     
  932.     // open the preferences file
  933.     h = Get1Resource('STR ', kPrefsFileResourceID);
  934.     if (h == nil)
  935.         return ResError();
  936.     DetachResource(h);
  937.     HLock(h);    
  938.     err = FSMakeFSSpec(volumeRef, dirID, (ConstStr255Param) *h, &prefsSpec);
  939.     HUnlock(h);
  940.     DisposeHandle(h);
  941.     if (err == noErr)
  942.     {
  943.         fileRef = FSpOpenResFile(&prefsSpec, fsRdPerm);
  944.         err = ResError();
  945.         
  946.         if (err == noErr)
  947.         {
  948.             // setup the preferences flags
  949.             h = Get1Resource('win ', kWinPosPrefsID);
  950.             if (h == nil)
  951.             {
  952.                 err = resNotFound;
  953.             }
  954.             else
  955.             {
  956.                 *r = **((Rect **) h);
  957.                 ReleaseResource(h);
  958.             }
  959.             CloseResFile(fileRef);
  960.         }
  961.     }
  962.     return err;
  963. }
  964.  
  965. //////////////////////////////////////////////////////////////////////////////
  966. //
  967. //    InitPrefs
  968. //
  969. //    Read the preferences from the prefs file or create it if it does not exist
  970. //
  971. OSErr InitPrefs (void)
  972. {
  973.     Handle            h;
  974.     Str63            menuString;
  975.     FSSpec            prefsSpec;
  976.     SInt32            dirID;
  977.     SInt16            vRefNum;
  978.     SInt16            fileRefNum;
  979.     SInt16            oldResFile;
  980.     OSErr            err;
  981.     Boolean            needsUpdate;
  982.  
  983.     // find the preferences folder
  984.     err = FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, &vRefNum, &dirID);
  985.     if (err != noErr)
  986.         return err;
  987.     
  988.     // create the preferences file if it does not exist
  989.     h = Get1Resource('STR ', kPrefsFileResourceID);
  990.     if (h == nil)
  991.         return ResError();
  992.     DetachResource(h);
  993.     HLock(h);    
  994.     err = FSMakeFSSpec(vRefNum, dirID, (ConstStr255Param) *h, &prefsSpec);
  995.     HUnlock(h);
  996.     DisposeHandle(h);
  997.     if (err == fnfErr)
  998.     {
  999.         FSpCreateResFile(&prefsSpec, 'fwfx', 'pref', smSystemScript);
  1000.         err = ResError();
  1001.         if (err != noErr)
  1002.             return err;
  1003.     }
  1004.  
  1005.     oldResFile = CurResFile();
  1006.     fileRefNum = FSpOpenResFile(&prefsSpec, fsRdWrPerm);
  1007.     err = ResError();
  1008.     if (err != noErr)
  1009.     {
  1010.         // file may exist but have no resource fork, create one and open it
  1011.         FSpCreateResFile(&prefsSpec, 'fwfx', 'pref', smSystemScript);
  1012.         err = ResError();
  1013.         if (err != noErr)
  1014.             return err;
  1015.         fileRefNum = FSpOpenResFile(&prefsSpec, fsRdWrPerm);
  1016.         err = ResError();
  1017.         if (err != noErr)
  1018.             return err;
  1019.     }
  1020.     
  1021.     // setup the preferences flags
  1022.     h = Get1Resource(kPrefsResourceType, kPrefsResourceID);
  1023.     if (h == nil)
  1024.     {
  1025.         h = NewHandle(4);
  1026.         **((UInt32 **) h) = gpFWXAppData->fwixPrefs = 1;
  1027.         AddResource(h, kPrefsResourceType, kPrefsResourceID, nil);
  1028.         UpdateResFile(fileRefNum);
  1029.         ReleaseResource(h);
  1030.     }
  1031.     else
  1032.     {
  1033.         gpFWXAppData->fwixPrefs = **((UInt32 **) h);
  1034.         ReleaseResource(h);
  1035.     }
  1036.     
  1037.     // setup the notification sound preferences
  1038.     h = Get1Resource('STR ', kSndPrefsResourceID);
  1039.     if (h == nil)
  1040.     {
  1041.         UseResFile(oldResFile);
  1042.         h = Get1Resource('STR ', kSndPrefsResourceID);
  1043.         if (h == nil)
  1044.             return ResError();
  1045.         DetachResource(h);
  1046.         UseResFile(fileRefNum);
  1047.         AddResource(h, 'STR ', kSndPrefsResourceID, nil);
  1048.         UpdateResFile(fileRefNum);
  1049.         BlockMove(*h, gpFWXAppData->fwixNotifySound, **h + 1);
  1050.         ReleaseResource(h);
  1051.     }
  1052.     else
  1053.     {    
  1054.         BlockMove(*h, gpFWXAppData->fwixNotifySound, **h + 1);
  1055.         ReleaseResource(h);
  1056.     }
  1057.     
  1058.     // setup receive folder
  1059.     h = Get1Resource(rAliasType, kDropPrefsResourceID);
  1060.     if (h == nil)
  1061.     {
  1062.         // retrieve receive folder name
  1063.         UseResFile(oldResFile);
  1064.         h = Get1Resource('STR ', kDropPrefsResourceID);
  1065.         if (h == nil)
  1066.             return ResError();
  1067.         FindFolder(kOnSystemDisk, kDesktopFolderType, kDontCreateFolder, &vRefNum, &dirID);
  1068.         DetachResource(h);
  1069.         HLock(h);    
  1070.         err = FSMakeFSSpec(vRefNum, dirID, (ConstStr255Param) *h, &gpFWXAppData->fwixReceiveFolder);
  1071.         if (err == fnfErr)
  1072.             err = FSpDirCreate(&gpFWXAppData->fwixReceiveFolder, smSystemScript, &dirID);
  1073.         HUnlock(h);
  1074.         DisposeHandle(h);
  1075.  
  1076.         // update the resource
  1077.         err = NewAliasMinimal(&gpFWXAppData->fwixReceiveFolder, (AliasHandle *) &h);
  1078.         UseResFile(fileRefNum);
  1079.         AddResource(h, rAliasType, kDropPrefsResourceID, nil);
  1080.         UpdateResFile(fileRefNum);
  1081.         ReleaseResource(h);
  1082.     }
  1083.     else
  1084.     {
  1085.         // got alias, try to resolve it
  1086.         DetachResource(h);
  1087.         err = ResolveAlias(nil, (AliasHandle) h, &gpFWXAppData->fwixReceiveFolder, &needsUpdate);
  1088.         if ((err != noErr) && (err != fnfErr))
  1089.         {
  1090.             // can't resolve alias, re-init receive folder preferences
  1091.             DisposeHandle(h);
  1092.             
  1093.             UseResFile(oldResFile);
  1094.             h = Get1Resource('STR ', kDropPrefsResourceID);
  1095.             if (h == nil)
  1096.                 return ResError();
  1097.             FindFolder(kOnSystemDisk, kDesktopFolderType, kDontCreateFolder, &vRefNum, &dirID);
  1098.             DetachResource(h);
  1099.             HLock(h);    
  1100.             err = FSMakeFSSpec(vRefNum, dirID, (ConstStr255Param) *h, &gpFWXAppData->fwixReceiveFolder);
  1101.             if (err == fnfErr)
  1102.                 err = noErr;
  1103.             HUnlock(h);
  1104.             DisposeHandle(h);
  1105.  
  1106.             // update the resource
  1107.             err = NewAliasMinimal(&gpFWXAppData->fwixReceiveFolder, (AliasHandle *) &h);
  1108.             UseResFile(fileRefNum);
  1109.             AddResource(h, rAliasType, kDropPrefsResourceID, nil);
  1110.             UpdateResFile(fileRefNum);
  1111.             ReleaseResource(h);
  1112.         }
  1113.         else if (needsUpdate)
  1114.         {
  1115.             AddResource(h, rAliasType, kDropPrefsResourceID, nil);
  1116.             UpdateResFile(fileRefNum);
  1117.             ReleaseResource(h);
  1118.         }
  1119.     }
  1120.     CloseResFile(fileRefNum);
  1121.     FlushVol(nil, vRefNum);
  1122.     UseResFile(oldResFile);
  1123.                         
  1124.     // make sure receive folder exists and update open receive folder menu string
  1125.     err = FSpDirCreate(&gpFWXAppData->fwixReceiveFolder, smSystemScript, &dirID);
  1126.     if (err == dupFNErr)
  1127.         err = noErr;
  1128.  
  1129.     GetMenuItemText(GetMenuHandle(kFileMenuID), kOpenDropMenuItem, menuString);
  1130.     BlockMove (gpFWXAppData->fwixReceiveFolder.name + 1,
  1131.                 menuString + 7,
  1132.                 gpFWXAppData->fwixReceiveFolder.name[0]);
  1133.     menuString[0] = 6 + gpFWXAppData->fwixReceiveFolder.name[0] + 1;
  1134.     menuString[menuString[0]] = '”';
  1135.     SetMenuItemText(GetMenuHandle(kFileMenuID), kOpenDropMenuItem, menuString);
  1136.         
  1137.     return err;
  1138. }            
  1139.